<?php

namespace App\Library\Logic;

use App\Models\ProductSpecModel;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;

class ProductSpecLogic extends ProductSpecModel
{
    public static function getByIds(array $array): Collection|array
    {
        $orderBy = 'field(ps_id,' . implode(',', $array) . ')';
        return self::query()->leftJoin('shop_product', 'shop_product.product_id', 'shop_product_specs.product_id')
            ->whereIn('ps_id', $array)->where([
                'product_status' => 2,
                'ps_is_delete' => 2,
                ['shop_product_specs.product_id', '>', 0],
                'shop_product.deleted_at' => null,
                'shop_product.plug' => 0,
            ])->orderBy(DB::raw($orderBy))->get([
                'ps_id',
                'ps_name',
                'product_avatar',
                'ps_avatar',
                'ps_price_underlined',
                'ps_price',
                'ps_usable_stock',
                'ps_buy_limit',
                'shop_product_specs.product_id',
                'shop_product.user_id',
                'product_name',
                'sub_price',
                'product_special_start_time',
                'product_special_end_time',
                DB::raw("from_unixtime(product_special_start_time, '%Y-%m-%d %H:%i:%s') as startAt"),
                DB::raw("from_unixtime(product_special_end_time, '%Y-%m-%d %H:%i:%s') as endAt"),
                'is_agent',
                'product_category_id_1',
            ]);
    }

    public static function buyWill(array $ids): Collection|array
    {
        $orderBy = 'field(ps_id,' . implode(',', $ids) . ')';
        return self::query()->leftJoin('shop_product', 'shop_product.product_id', 'shop_product_specs.product_id')
            ->whereIn('ps_id', $ids)->where([
                'product_status' => 2,
                ['shop_product_specs.product_id', '>', 0],
            ])->orderBy(DB::raw($orderBy))->get([
                'shop_product_specs.serial_number',
                'ps_id',
                'shop_product.product_id',
                'ps_name',
                'product_avatar',
                'ps_avatar',
                'buy_will_price',
                'ps_usable_stock',
                'ps_buy_limit',
                'shop_product_specs.product_id',
                'shop_product.user_id',
                'product_name',
            ]);
    }

    public static function checkByIds(array $array): Collection|array
    {
        return self::query()->leftJoin('shop_product', 'shop_product.product_id', 'shop_product_specs.product_id')
            ->whereIn('ps_id', $array)->where('shop_product_specs.product_id', '>', 0)->with('buyCount')->get([
                'ps_id', 'ps_is_delete', 'product_status', 'ps_usable_stock', 'ps_buy_limit',
            ]);
    }

    public static function decStock(array $data): void
    {
        $ids = [];
        foreach ($data as $v) {
            if (!in_array($v['productId'], $ids)) $ids[] = $v['productId'];
            $psUsableStock = $v['psUsableStock'] > $v['quantity'] ? DB::raw('ps_usable_stock-' . $v['quantity']) : 0;
            self::query()->where('ps_id', $v['specId'])->update([
                'ps_usable_stock' => $psUsableStock,
                'ps_disable_stock' => DB::raw('ps_disable_stock+' . $v['quantity']),
            ]);
        }
        self::handleProductStock($ids);
    }

    public static function decStockByConfirm(Model $order): void
    {
        $ids = [];
        foreach ($order->goods as $v) {
            if (!in_array($v->product_id, $ids)) $ids[] = $v->product_id;
            $spec = self::detail($v->spec_id, ['psId', 'psDisableStock', 'psTotalStock']);
            if ($spec->ps_disable_stock >= $v->quantity) $spec->ps_disable_stock -= $v->quantity;
            if ($spec->ps_total_stock >= $v->quantity) $spec->ps_total_stock -= $v->quantity;
            $spec->save();
        }
        self::handleProductStock($ids);
    }

    public static function incStock(int $orderId): void
    {
        $ids = [];
        $list = ShopOrderGoodsLogic::getByWhere('orderId', $orderId);
        foreach ($list as $v) {
            if ($v->product_id === 0 && $v->spec_id === 0) continue;
            if (!in_array($v->product_id, $ids)) $ids[] = $v->product_id;
            $psDisableStock = self::valueByWhere('psId', $v->spec_id, 'psDisableStock');
            if (is_null($psDisableStock)) $psDisableStock = 0;
            else $psDisableStock = $psDisableStock > $v->quantity ? DB::raw('ps_disable_stock-' . $v->quantity) : 0;
            self::query()->where('ps_id', $v->spec_id)->update([
                'ps_usable_stock' => DB::raw('ps_usable_stock+' . $v->quantity),
                'ps_disable_stock' => $psDisableStock,
            ]);
        }
        self::handleProductStock($ids);
    }

    private static function handleProductStock(array $ids): void
    {
        foreach ($ids as $v) {
            if (self::sumByWhere('product_id', $v, 'ps_usable_stock') > 0) $status = 1;//有可用库存
            else {
                if (self::sumByWhere('product_id', $v, 'ps_disable_stock') <= 0) $status = 2;//售罄无可用库存
                else $status = 3;//占用无可用库存
            }
            ShopProductLogic::query()->where('product_id', $v)->update(['product_stock_empty' => $status]);
        }
    }

    /**
     * 获取规格佣金信息
     * @param int $productId
     * @return array
     *
     */
    public static function getSpecsCommissionInfo(int $productId): array
    {
        return ProductSpecLogic::query()->where(['product_id' => $productId])
            ->select(DB::raw('
                        ps_id,
                        ps_price,
                        ps_price_underlined,
                        cast(IFNULL(if(commission > 0, commission, null), 0) as double) as commission,
                        cast(IFNULL(if(commission_ratio > 0, (commission_ratio * ps_price) / 100, null), 0) as double) as commission_ratio,
                        cast(IFNULL(if(commission_ratio > 0, (commission_ratio * ps_price_underlined) / 100, null), 0) as double) as underline_commission_ratio
                    '))->get()->toArray();
    }
}
